<?php

/**
 * @see \Kaeru\Model\Property\IPropertyProxy
 */
require_once 'Kaeru/Model/Property/IPropertyProxy.php';

/**
 * The PropertyProxy acts as a proxy replacing a null property value with a new
 * value (usually another model or an array of models).
 */
class PropertyProxy extends Object implements IPropertyProxy
{
    /**
     *
     * @var \Kaeru\Model\Dao\DaoFactory
     */
    protected $daoFactory;

    /**
     * An array of settings for every property that can be proxied to something
     * else on the model.
     *
     * Example:
     * 'parent' => array(
     *        'dao' => 'Parent',
     *        'method' => 'get',
     *        'params' => array(
     *            '@id'
     *        )
     *    ),
     * 'children' => array(
     *        'dao' => 'Child',
     *        'method' => 'getCollectionByParent',
     *        'params' => array(
     *            '@id',
     *            array(
     *                'limit' => 10,
     *                'orderBy' => 'id',
     *                'orderDir' => 'ASC'
     *            )
     *        )
     * )
     *
     * @var array
     */
    protected $properties = array();

    /**
     * Constructor.
     *
     * @param array $properties
     * @param \Kaeru\Model\Dao\DaoFactory
     * @return \Kaeru\Model\Property\PropertyProxy
     */
    public function __construct(array $properties, DaoFactory $daoFactory)
    {
        $this->properties = $properties;
        $this->daoFactory = $daoFactory;
        return $this;
    }

    /**
     * Executes the property proxy and replaces $property on the $model with the
     * result fetched from the DAO called. If a property settings param is
     * prepended with '@', the param value will be fetched from the $model by
     * accessing the model property with the same name as the param.
     *
     * @param string $property
     * @param \Kaeru\Model\AbstractModel $model
     * @return \Kaeru\Model\Property\PropertyProxy
     */
    public function execute($property, AbstractModel $model)
    {
        $propertySettings = $this->properties[$property];
        
        $params = $propertySettings['params'];

        foreach ($params as $index => $param) {
            if (is_string($param) && strpos($param, '@') === 0) {
                $propertyParam = ltrim($param, '@');
                $params[$index] = $model->{$propertyParam};
            }
        }

        $dao = $this->daoFactory->get($propertySettings['dao']);
        $daoMethod = $propertySettings['method'];

        $result = call_user_func_array(array($dao, $daoMethod), $params);
        
        $model->$property = $result;

        return $this;
    }
}